/*
 * Copyright © 2018 www.noark.xyz All Rights Reserved.
 *
 * 感谢您选择Noark框架，希望我们的努力能为您提供一个简单、易用、稳定的服务器端框架 ！
 * 除非符合Noark许可协议，否则不得使用该文件，您可以下载许可协议文件：
 *
 *        http://www.noark.xyz/LICENSE
 *
 * 1.未经许可，任何公司及个人不得以任何方式或理由对本框架进行修改、使用和传播;
 * 2.禁止在本项目或任何子项目的基础上发展任何派生版本、修改版本或第三方版本;
 * 3.无论你对源代码做出任何修改和改进，版权都归Noark研发团队所有，我们保留所有权利;
 * 4.凡侵犯Noark版权等知识产权的，必依法追究其法律责任，特此郑重法律声明！
 */
package xyz.noark.codec.schema;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class ByteArrayPool {
    private final int initialCapacity;
    private final int maxCapacity;
    private final long idleTimeoutMillis;
    private final ConcurrentLinkedQueue<byte[]> pool;
    private final AtomicInteger count;

    public ByteArrayPool(int initialCapacity, int maxCapacity, long idleTimeoutMillis) {
        if (initialCapacity < 0 || maxCapacity < initialCapacity || idleTimeoutMillis <= 0) {
            throw new IllegalArgumentException("Invalid parameters");
        }
        this.initialCapacity = initialCapacity;
        this.maxCapacity = maxCapacity;
        this.idleTimeoutMillis = idleTimeoutMillis;
        this.pool = new ConcurrentLinkedQueue<>();
        this.count = new AtomicInteger(initialCapacity);

        // 初始化池
        for (int i = 0; i < initialCapacity; i++) {
            pool.add(new byte[1024]); // 默认大小为1024字节，可根据需要调整
        }
    }

    public synchronized byte[] acquire() {
        byte[] buffer = pool.poll();
        if (buffer == null && count.get() < maxCapacity) {
            buffer = new byte[1024];
            pool.add(buffer);
            count.incrementAndGet();
        }
        return buffer;
    }

    public synchronized void release(byte[] buffer) {
        if (buffer != null) {
            // 清空buffer，以保证安全重用
            java.util.Arrays.fill(buffer, (byte) 0);
            pool.add(buffer);
        }
    }

    private void cleanUp() {
        long currentTime = System.currentTimeMillis();
        Queue<byte[]> toRemove = new LinkedList<>();

        for (byte[] buffer : pool) {
            // 假设每个buffer有一个时间戳，这里简单地模拟一个时间戳
            long timestamp = getCurrentTimestamp(buffer);
            if (currentTime - timestamp > idleTimeoutMillis) {
                toRemove.add(buffer);
            }
        }

        for (byte[] buffer : toRemove) {
            pool.remove(buffer);
            count.decrementAndGet();
        }
    }

    private long getCurrentTimestamp(byte[] buffer) {
        // 这里只是一个示例，实际应用中可以使用某种机制来记录每个buffer的最后使用时间
        return System.currentTimeMillis(); // 返回当前时间作为示例
    }

    public void runCleanupTask() {
        // 定时任务，定期清理
        while (true) {
            try {
                TimeUnit.SECONDS.sleep(60); // 每60秒执行一次
                cleanUp();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                break;
            }
        }
    }

    public static void main(String[] args) {
        ByteArrayPool byteArrayPool = new ByteArrayPool(10, 50, 60000); // 初始容量10，最大容量50，闲置超时时间为60秒
        Thread cleanupThread = new Thread(byteArrayPool::runCleanupTask);
        cleanupThread.start();

        // 测试代码
        byte[] buffer = byteArrayPool.acquire();
        System.out.println("Acquired buffer: " + buffer);
        byteArrayPool.release(buffer);
    }
}
